package ynu.edu.item.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import ynu.edu.api.dto.ItemDTO;
import ynu.edu.api.dto.OrderDetailDTO;
import ynu.edu.common.exception.BizIllegalException;
import ynu.edu.common.utils.BeanUtils;
import ynu.edu.item.domain.po.Item;
import ynu.edu.item.mapper.ItemMapper;
import ynu.edu.item.service.IItemService;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Slf4j
@Service
@RequiredArgsConstructor
public class ItemServiceImpl extends ServiceImpl<ItemMapper, Item> implements IItemService {

    /**
     * 扣减库存
     * @param items 订单商品列表
     */
    @Override
    @Transactional
    public void deductStock(List<OrderDetailDTO> items) {
        if (items == null || items.isEmpty()) {
            log.warn("扣减库存：商品列表为空");
            return;
        }

        log.info("开始扣减库存，商品数量：{}", items.size());
        
        for (OrderDetailDTO item : items) {
            if (item.getItemId() == null || item.getNum() == null || item.getNum() <= 0) {
                throw new BizIllegalException("商品ID或数量无效");
            }
            
            // 使用乐观锁方式扣减库存
            LambdaUpdateWrapper<Item> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.eq(Item::getId, item.getItemId())
                    .ge(Item::getStock, item.getNum()) // 库存必须大于等于购买数量
                    .setSql("stock = stock - " + item.getNum());
            
            boolean success = update(updateWrapper);
            if (!success) {
                log.error("扣减库存失败，商品ID：{}，购买数量：{}", item.getItemId(), item.getNum());
                throw new BizIllegalException("商品库存不足！");
            }
            
            log.info("商品{}库存扣减成功，扣减数量：{}", item.getItemId(), item.getNum());
        }
        
        log.info("库存扣减完成，共处理{}个商品", items.size());
    }

    /**
     * 恢复库存
     * @param items 订单商品列表
     */
    @Override
    @Transactional
    public Boolean restoreStock(List<OrderDetailDTO> items) {
        if (items == null || items.isEmpty()) {
            log.warn("恢复库存：商品列表为空");
            return  true;
        }

        log.info("开始恢复库存，商品数量：{}", items.size());
        
        for (OrderDetailDTO item : items) {
            if (item.getItemId() == null || item.getNum() == null || item.getNum() <= 0) {
                throw new BizIllegalException("商品ID或数量无效");
            }
            
            // 恢复库存
            LambdaUpdateWrapper<Item> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.eq(Item::getId, item.getItemId())
                    .setSql("stock = stock + " + item.getNum());
            
            boolean success = update(updateWrapper);
            if (!success) {
                log.error("恢复库存失败，商品ID：{}，恢复数量：{}", item.getItemId(), item.getNum());
                throw new BizIllegalException("恢复库存失败！");
            }
            
            log.info("商品{}库存恢复成功，恢复数量：{}", item.getItemId(), item.getNum());
        }
        
        log.info("库存恢复完成，共处理{}个商品", items.size());
        return true;
    }

    /**
     * 批量查询商品
     * @param ids 商品ID集合
     * @return 商品DTO列表
     */
    @Override
    public List<ItemDTO> queryItemByIds(Collection<Long> ids) {
        if (ids == null || ids.isEmpty()) {
            log.warn("查询商品：ID列表为空");
            return List.of();
        }

        log.info("开始查询商品，商品ID数量：{}", ids.size());
        
        // 使用MyBatis-Plus的listByIds方法
        List<Item> items = listByIds(ids);
        
        if (items.size() < ids.size()) {
            log.warn("部分商品不存在，查询到{}个商品，请求{}个商品ID", items.size(), ids.size());
        }
        
        List<ItemDTO> itemDTOs = BeanUtils.copyList(items, ItemDTO.class);
        log.info("商品查询完成，返回{}个商品", itemDTOs.size());
        
        return itemDTOs;
    }

    /**
     * 检查库存是否充足
     * @param items 订单商品列表
     * @return 是否库存充足
     */
    public boolean checkStock(List<OrderDetailDTO> items) {
        if (items == null || items.isEmpty()) {
            return true;
        }

        // 获取所有商品ID
        List<Long> itemIds = items.stream()
                .map(OrderDetailDTO::getItemId)
                .collect(Collectors.toList());

        // 查询商品库存
        List<Item> itemsWithStock = listByIds(itemIds);
        Map<Long, Item> itemMap = itemsWithStock.stream()
                .collect(Collectors.toMap(Item::getId, item -> item));

        // 检查每个商品的库存
        for (OrderDetailDTO orderItem : items) {
            Item item = itemMap.get(orderItem.getItemId());
            if (item == null) {
                log.error("商品不存在，商品ID：{}", orderItem.getItemId());
                return false;
            }
            
            if (item.getStock() < orderItem.getNum()) {
                log.error("商品库存不足，商品ID：{}，库存：{}，需求：{}", 
                        orderItem.getItemId(), item.getStock(), orderItem.getNum());
                return false;
            }
        }

        return true;
    }

    /**
     * 获取商品库存信息
     * @param itemId 商品ID
     * @return 库存数量
     */
    public Integer getItemStock(Long itemId) {
        if (itemId == null) {
            return 0;
        }

        Item item = getById(itemId);
        return item != null ? item.getStock() : 0;
    }

    /**
     * 根据商品类别查询商品
     * @param category 商品类别
     * @return 商品DTO列表
     */
    @Override
    public List<ItemDTO> queryItemsByCategory(String category) {
        if (category == null || category.trim().isEmpty()) {
            log.warn("查询商品：类别参数为空");
            return List.of();
        }

        log.info("开始查询商品，类别：{}", category);
        
        // 使用MyBatis-Plus的lambdaQuery方法查询指定类别的商品
        List<Item> items = lambdaQuery()
                .eq(Item::getCategory, category.trim())
                .eq(Item::getStatus, 1) // 只查询上架状态的商品
                .orderByDesc(Item::getUpdateTime) // 按更新时间倒序
                .list();
        
        List<ItemDTO> itemDTOs = BeanUtils.copyList(items, ItemDTO.class);
        log.info("类别商品查询完成，类别：{}，返回{}个商品", category, itemDTOs.size());
        
        return itemDTOs;
    }
}
